package io.github.flylinran.common.aspect;

import io.github.flylinran.common.exception.BaseException;
import io.github.flylinran.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.stream.Collectors;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BaseException.class)
    public R handleBaseException(BaseException e) {
        log.warn(e.getMessage(), e);
        return R.error(e.getCode(), e.getMsg());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.warn(e.getMessage(), e);
        return R.error(400, "请求参数格式错误");
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public R handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
        log.warn(e.getMessage(), e);
        return R.error(400, "请求参数格式不匹配");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public R handleDuplicateKeyException(DuplicateKeyException e) {
        log.warn(e.getMessage(), e);
        return R.error("数据库中已存在该记录");
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public R defaultMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.warn(e.getMessage(), e);
        return R.error(buildBindingResultMessage(e.getBindingResult()));
    }

    @ExceptionHandler({BindException.class})
    public R beanPropertyBindingResult(BindException e) {
        log.warn(e.getMessage(), e);
        return R.error(buildBindingResultMessage(e.getBindingResult()));
    }

    @ExceptionHandler(NullPointerException.class)
    public R handleNullPointerException(NullPointerException e) {
        log.warn(e.getMessage(), e);
        return R.error("不存在此条数据");
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public R handleIllegalArgumentException(IllegalArgumentException e) {
        log.warn(e.getMessage(), e);
        return R.error("不存在此条数据");
    }

    @ExceptionHandler(Exception.class)
    public R handleException(Exception e) {
        log.warn(e.getMessage(), e);
        return R.error(e.getMessage());
    }

    private String buildBindingResultMessage(BindingResult bindingResult) {
        return bindingResult.getFieldErrors()
                .stream().map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.toList()).toString();
    }
}
